package com.ruoyi.business.processIou.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.mapper.ExtMonnifyReservedAccountsMapper;
import com.ruoyi.bizsys.mapper.ReduceFeeMapper;
import com.ruoyi.bizsys.mapper.RepaymentOrderMapper;
import com.ruoyi.bizsys.service.ICreditAccountService;
import com.ruoyi.bizsys.service.IExtMonnifyOrderService;
import com.ruoyi.bizsys.service.ILoanIouService;
import com.ruoyi.bizsys.service.ILoanOverflowService;
import com.ruoyi.bizsys.utils.BizConstants;
import com.ruoyi.business.domain.TransferVo;
import com.ruoyi.business.service.IMonnifyRepaymentService;
import com.ruoyi.business.service.IRepayToWalletService;
import com.ruoyi.business.util.MonnifyUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.extdata.service.IExternalApiService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDictDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

/**
 * @author wqg
 * @description
 * @date 2022/6/23
 */
@Slf4j
@Component
public class DoMonnifyFinanceService {

    @Autowired
    IExternalApiService iExternalApiService;
    @Autowired
    IExtMonnifyOrderService iExtMonnifyOrderService;
    @Autowired
    ISysDictDataService sysDictDataService;
    @Autowired
    ISysConfigService iSysConfigService;
    @Lazy
    @Autowired
    IMonnifyRepaymentService monnifyRepaymentService;

    @Autowired
    ILoanIouService loanIouService;

    @Autowired
    ILoanOverflowService iLoanOverflowService;

    @Autowired
    ICreditAccountService creditAccountService;

    @Autowired
    ReduceFeeMapper reduceFeeMapper;

    @Autowired
    ILoanOffsetChangeRecordService loanOffsetChangeRecordService;

    @Autowired
    RepaymentOrderMapper repaymentOrderMapper;

    @Autowired
    ExtMonnifyReservedAccountsMapper extMonnifyReservedAccountsMapper;

    @Autowired
    IRepayToWalletService repayToWalletService;

//    @PostConstruct
//    public void test() throws ParseException {
//        doMonnifyForFinance("20220529060436202583879681", "8232932285");
//    }

    /**
     * // 查询 monnifyGetAllTransactionsOnReservedAccount 获取所有的数据
     * // 查 monnifyRepaymentService 查询所有数据后续进行对比
     *
     * @return
     */
    public JSONObject doMonnifyForFinance(String loanSerialNo, String accountsAccountNumber) throws ParseException {
        JSONObject res = new JSONObject();
        res.put("status", 0);
        ExtMonnifyReservedAccounts extMonnifyReservedAccounts =
                extMonnifyReservedAccountsMapper.selectByaccountsAccountNumber(accountsAccountNumber);
        if (null == extMonnifyReservedAccounts) {
            res.put("msg", "虚拟账号已经失效");
            return res;
        }
        String accountReference = extMonnifyReservedAccounts.getAccountReference();
        LoanIou loanIou = loanIouService.getLoanIouByLoanSerialNo(loanSerialNo);
        // 再次查询借据是否使用了1次回溯
        //ReduceFee reduceFee = reduceFeeMapper.selectOneBySerialNoAndType(loanSerialNo,ReduceFee.ACTION_TYPE_MONNIFLY_FINANCE);
        if (null != loanIou.getNumFinance() && loanIou.getNumFinance() > 0) {
            res.put("msg", "已经使用了1次回溯");
            return res;
        }
        //获取全部订单
        int page = 0;
        int size = 20;
        JSONObject jsonObject = null;
        boolean isMock = Integer.parseInt(sysDictDataService.selectDictLabel("biz_switch", "api_paystack_mock")) == 1;
        if (isMock) {
            jsonObject = JSONObject.parseObject(iSysConfigService.selectConfigByKey("MonniflyResfor|" + accountReference));
            log.info("外部接口MonnifyResforMock {} 返回模拟报文：{}", jsonObject.toJSONString());
        } else {
            jsonObject = iExternalApiService.monnifyGetAllTransactionsOnReservedAccount(accountReference, page, size);
        }
        JSONArray content = jsonObject.getJSONArray("content");
        if (content.size() == 0) {
            res.put("msg", "没有Monnify数据");
            return res;
        }
        List<String> extMonnifyOrderList = iExtMonnifyOrderService.getListStringByCustNo(loanIou.getCustNo());

        boolean repayToWalletFlag = false;
        String repayToWalletSwitch = sysDictDataService.selectDictLabel("biz_switch", "repay_to_wallet_switch");
        if (StringUtils.equals(BizConstants.BIZ_SWITCH_OPEN, repayToWalletSwitch)) {
            log.info("还款金额直接充值钱包开关开启");
            repayToWalletFlag = true;
        }

        // 由远到近检查completedOn是否<借据创建时间 需要处理JSON
        JSONArray contentList = jsonArraySort(content);
        boolean hasHuisu = false;
        for (int i = 0; i < contentList.size(); i++) {
            JSONObject json = contentList.getJSONObject(i);
            String paymentReference = json.getString("paymentReference");
            if (!extMonnifyOrderList.contains(paymentReference)) {
                String paymentStatus = json.getString("paymentStatus");
                if ("PAID".equals(paymentStatus)) {
                    ExtMonnifyOrder extMonnifyOrder = MonnifyUtils.setExtMonnifyOrderInterface(json, accountReference, loanIou.getCustNo());
                    iExtMonnifyOrderService.insertExtMonnifyOrder(extMonnifyOrder);

                    if (repayToWalletFlag) {
                        log.info("财务主动拉取还款金额直接充值钱包开关开启，不进入还款");
                        TransferVo transferVo = TransferVo.builder().custNo(loanIou.getCustNo()).transferAmt(extMonnifyOrder.getAmountPaid()).actionType(BizConstants.OVERFLOW_TYPE_FINANCE_CAL).reference(extMonnifyOrder.getTransactionReference()).payTime(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, extMonnifyOrder.getPaidOn())).build();
                        repayToWalletService.addOverflowAndPushWallet(transferVo);
                        continue;
                    }
                    loanIou = loanIouService.getLoanIouByLoanSerialNo(loanSerialNo);
                    if (loanIou.getIouStatus() == LoanIou.LOAN_IOU_STATUS_SETTLE) {
                        TransferVo transferVo = TransferVo.builder().custNo(loanIou.getCustNo()).transferAmt(extMonnifyOrder.getAmountPaid()).actionType(BizConstants.OVERFLOW_TYPE_FINANCE_CAL).reference(extMonnifyOrder.getTransactionReference()).payTime(DateUtils.dateTime(DateUtils.YYYY_MM_DD_HH_MM_SS, extMonnifyOrder.getPaidOn())).build();
                        repayToWalletService.addOverflowAndPushWallet(transferVo);
                        continue;
                    }

                    // 存在需要查询的
                    doPross(loanIou, json, res, hasHuisu);
                }
            }
        }
        res.put("status", 1);
        return res;
    }

    private void doPross(LoanIou loanIou, JSONObject json, JSONObject res, boolean hasHuisu) throws ParseException {
        JSONArray arrayJson = new JSONArray();
        JSONObject data = new JSONObject();
        String paymentReference = json.getString("paymentReference");
        Date completedOn = DateUtils.parseUTCText(json.getString("completedOn"));
        // Date completedOn = DateUtils.addHours(completedOnTemp, -8);
        String completedOnStr = DateUtils.formatDate(completedOn, "yyyy-MM-dd HH:mm:ss");
        BigDecimal amountPaid = json.getBigDecimal("amountPaid");
        log.info(paymentReference + ": createdOn:{},amountPaid:{}", completedOn, amountPaid);
        // 判断当前的借据 和 completedOn判断是前还是后
        String iouCreateTime = DateUtils.formatDate(loanIou.getCreateTime(), "yyyy-MM-dd HH:mm:ss");
        data.put("reference", paymentReference);
        data.put("time", completedOn);
        data.put("amountPaid", amountPaid);
        if (DateUtils.compareTimes(completedOnStr, iouCreateTime, "yyyy-MM-dd HH:mm:ss") == -1) {
            // 小于iou时间 生成溢缴款
            if (null == iLoanOverflowService.selectOneByHas(loanIou.getCustNo(), paymentReference)) {
                createLoanOverFlow(json, loanIou.getCustNo(), paymentReference, completedOn);
                data.put("type", 1);
                arrayJson.add(data);
                res.put("resList", arrayJson);
            }
            return;
        }
        if (!hasHuisu) {
            // 进行回溯  回溯也要进行是否结清，更新结清时间，多的进入溢缴款
            // 查询 设置 loanoffset repayorder 时间是completedOn，只能回溯一次
            // 调用回溯代码
            RepaymentOrder repaymentOrderSql = new RepaymentOrder();
            repaymentOrderSql.setPayTransSerialNo(paymentReference);
            repaymentOrderSql.setCustNo(loanIou.getCustNo());// 只能根据客户号，
            RepaymentOrder repaymentOrder = repaymentOrderMapper.getRepaymentOrderByPayTrans(repaymentOrderSql);
            if (null == repaymentOrder) {
                loanOffsetChangeRecordService.DoInsertLoanOffsetAndRepaymentOrder(loanIou, paymentReference, completedOn, amountPaid);
                hasHuisu = true;
                data.put("type", 2);
                arrayJson.add(data);
                res.put("resList", arrayJson);
            } else {
                log.info(paymentReference + "已经存在不需要回溯！");
            }
        }
    }

    private void createLoanOverFlow(JSONObject json, String custNo, String paymentReference, Date completedOn) {
        ExtMonnifyOrder extMonnifyOrder = MonnifyUtils.setExtMonnifyOrderInterface(json, paymentReference, custNo);
        LoanOverflow loanOverflow = new LoanOverflow();
        loanOverflow.setChangeAmount(extMonnifyOrder.getAmountPaid());
        loanOverflow.setCustNo(extMonnifyOrder.getCustNo());
        loanOverflow.setOverflowTime(completedOn);
        loanOverflow.setType(BizConstants.OVERFLOW_TYPE_FINANCE_CAL);
        loanOverflow.setAccountReference(extMonnifyOrder.getProductReference());
        loanOverflow.setTransactionReference(extMonnifyOrder.getTransactionReference());
        loanOverflow.setMonnifyOrderId(extMonnifyOrder.getId());
        loanOverflow.setRemark("财务回溯completedOn:{" + completedOn + "}小于当前借据时间");

        TransferVo transferVo = TransferVo.builder().custNo(custNo).transferAmt(extMonnifyOrder.getAmountPaid()).actionType(BizConstants.OVERFLOW_TYPE_FINANCE_CAL).reference(extMonnifyOrder.getTransactionReference()).payTime(completedOn).build();
        repayToWalletService.addOverflowAndPushWallet(transferVo);

        // 修改用户溢缴金额
        // iLoanOverflowService.insertLoanOverflow(loanOverflow);
        // creditAccountService.updateOverflowAmount(extMonnifyOrder.getCustNo(), extMonnifyOrder.getAmountPaid());
    }


    /**
     * 按照JSONArray中的对象的某个字段进行排序(采用fastJson)
     *
     * @param jsonArr
     */
    public static JSONArray jsonArraySort(JSONArray jsonArr) {
        JSONArray sortedJsonArray = new JSONArray();
        List<JSONObject> jsonValues = new ArrayList<JSONObject>();
        for (int i = 0; i < jsonArr.size(); i++) {
            jsonValues.add(jsonArr.getJSONObject(i));
        }
        Collections.sort(jsonValues, new Comparator<JSONObject>() {
            private static final String KEY_NAME = "completedOn";
            String string1;
            String string2;

            @Override
            public int compare(JSONObject a, JSONObject b) {
                try {
                    Date completedOnTemp = DateUtils.parseUTCText(a.getString(KEY_NAME));
                    Date completedOn = DateUtils.addHours(completedOnTemp, -8);
                    String completedOnStr = DateUtils.formatDate(completedOn, "yyyy-MM-dd HH:mm:ss");
                    string1 = completedOnStr.replaceAll("-", "");
                    Date bcompletedOnTemp = DateUtils.parseUTCText(b.getString(KEY_NAME));
                    Date bcompletedOn = DateUtils.addHours(bcompletedOnTemp, -8);
                    String bcompletedOnStr = DateUtils.formatDate(bcompletedOn, "yyyy-MM-dd HH:mm:ss");
                    string2 = bcompletedOnStr.replaceAll("-", "");
                } catch (JSONException e) {
                    // 处理异常
                    log.error("JSONException", e.getMessage());
                } catch (ParseException e) {
                    log.error("ParseException", e.getMessage());
                }
                //这里是按照时间逆序排列,不加负号为正序排列
                return string1.compareTo(string2);
            }
        });
        for (int i = 0; i < jsonArr.size(); i++) {
            sortedJsonArray.add(jsonValues.get(i));
        }
        return sortedJsonArray;
    }


}
